package org.xiaojinlong.net;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class ServerSocketChannelTest {
    private static byte[] data = new byte[256];
    static {
        for (int i = 0; i < data.length; i++)
            data[i] = (byte)i;
    }

    public static void main(String[] args) throws IOException {
        //新建NIO通道
        ServerSocketChannel server = ServerSocketChannel.open();
        //使通道为非阻塞
        server.configureBlocking(false);
        //创建基于NIO通道的socket连接
        ServerSocket ss = server.socket();
        //新建socket通道的端口
        ss.bind(new InetSocketAddress("127.0.0.1", 9000));
        //将NIO通道绑定到选择器
        Selector selector = Selector.open();
        server.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            if (selector.select() == 0) continue;
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectedKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key =  iterator.next();
                iterator.remove();

                if (key.isAcceptable()) {
                    //获取对应的SocketChannel
                    SocketChannel client = server.accept();
                    System.out.println("Accepted connection from " + client);
                    //使此通道为非阻塞
                    client.configureBlocking(false);

                    //在此通道上注册事件
                    SelectionKey key2 = client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ);
                    //将数组data的大小定义为ByteBuffer缓冲区的大小
                    ByteBuffer source = ByteBuffer.wrap(data);
                    //通道执行事件
                    key2.attach(source);
                } else if (key.isWritable()) {
                    //获取此通道的SocketChannel
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer output = (ByteBuffer) key.attachment();
                    //如果缓存区没了,重置一下
                    if (!output.hasRemaining()) {
                        output.rewind();
                    }
                    //在此通道内写东西
                    client.write(output);
                } else if (key.isReadable()) {
                    SocketChannel client = (SocketChannel) key.channel();
                    ByteBuffer buffer =  ByteBuffer.allocate(256);
                    client.read(buffer);
                    System.out.println(buffer);
                }
                key.channel().close();
            }

        }

    }

}
